package com.fly.hello.web.async;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * Callback和DeferredResult用于设置单个结果<BR>
 * 如果有多个结果需要set返回给客户端时，可以使用SseEmitter以及ResponseBodyEmitter<BR>
 * StreamingResponseBody可用来直接写入到response的OutputStream<BR>
 * see: https://blog.csdn.net/f641385712/article/details/88710676
 */
@Slf4j
@RestController
@Api(tags = "deferredResult异步1")
@RequestMapping("/async1")
public class DeferredResult1Controller
{
    @ApiOperation("异步随机返回字符串或图片")
    @GetMapping("/test")
    public DeferredResult<Object> test(HttpServletResponse response)
    {
        DeferredResult<Object> deferredResult = new DeferredResult<>(20000L, "失败");
        deferredResult.onCompletion(() -> log.info("调用完成"));
        deferredResult.onTimeout(() -> {
            log.info("调用超时");
            deferredResult.setResult("调用超时");
        });
        processResult(deferredResult, response);
        return deferredResult;
    }
    
    /**
     * 业务线程处理业务,DeferredResult可以通过任何线程来计算返回一个结果
     * 
     * @param deferredResult
     * @see [类、类#方法、类#成员]
     */
    private void processResult(DeferredResult<Object> deferredResult, HttpServletResponse response)
    {
        new Thread(() -> {
            try
            {
                if (RandomUtils.nextBoolean())
                {
                    deferredResult.setResult("OK");
                }
                else
                {
                    response.setContentType(MediaType.IMAGE_JPEG_VALUE);
                    Resource resource = new ClassPathResource("data/pic/18.jpg");
                    try (InputStream input = resource.getInputStream())
                    {
                        deferredResult.setResult(IOUtils.toByteArray(input));
                    }
                }
            }
            catch (IOException e)
            {
                log.error(e.getMessage(), e);
            }
        }).start();
    }
}
